"""
MSC (多元散射校正) 处理器

MSC用于消除光谱中的散射效应，是近红外光谱预处理的经典方法。
通过线性回归将每个样本的光谱与平均光谱进行校正。
"""

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from ..base import PreprocessorInterface
from ..validation import validate_input_data, safe_copy_dataframe


class MSC(PreprocessorInterface):
    """
    多元散射校正 (Multiplicative Scatter Correction)
    
    消除光谱数据中的散射效应，提高光谱数据质量。
    原理：通过线性回归校正每个样本与平均光谱的关系
    """
    
    def process(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        对光谱数据进行MSC校正
        
        Args:
            data (pd.DataFrame): 输入光谱数据
            
        Returns:
            pd.DataFrame: MSC校正后的数据
        """
        # 验证输入数据
        validate_input_data(data)
        
        # 创建数据副本
        result = safe_copy_dataframe(data)
        
        # 获取光谱数据列（跳过第一列ID列）
        spectral_columns = result.columns[1:]
        spectral_data = result[spectral_columns].values
        
        # 计算平均光谱
        mean_spectrum = np.mean(spectral_data, axis=0)
        
        # 对每个样本进行MSC校正
        corrected_spectra = np.zeros_like(spectral_data)
        
        for i in range(spectral_data.shape[0]):
            spectrum = spectral_data[i, :]
            
            # 线性回归：spectrum = a * mean_spectrum + b
            # 重塑数据以适应sklearn
            X = mean_spectrum.reshape(-1, 1)
            y = spectrum.reshape(-1, 1)
            
            # 拟合线性回归
            reg = LinearRegression()
            reg.fit(X, y)
            
            # 获取回归系数
            a = reg.coef_[0][0]  # 斜率
            b = reg.intercept_[0]  # 截距
            
            # MSC校正：corrected = (spectrum - b) / a
            if abs(a) > 1e-10:  # 避免除以0
                corrected_spectra[i, :] = (spectrum - b) / a
            else:
                corrected_spectra[i, :] = spectrum  # 如果斜率接近0，保持原值
        
        # 将校正后的数据放回DataFrame
        result[spectral_columns] = corrected_spectra
        
        return result
    
    def get_name(self) -> str:
        """返回处理器名称"""
        return "MSC多元散射校正"
    
    def get_id(self) -> int:
        """返回唯一ID"""
        return 4